﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CollectionOperationKit
{
    public class ServerSideHelpers
    {
        public static object SetObjectProperty(object input, string name, object value)
        {
            if (input == null)
            {
                return null; // 如果输入为null，直接返回null
            }

            if (string.IsNullOrWhiteSpace(name) || name.ToLower() == "%value%")
            {
                return value; // 如果属性名为空或为%value%，直接返回值
            }

            if (input is IDictionary<string, object> dic)
            {
                // 使用命令创建的，直接写入
                if (dic.ContainsKey(name))
                {
                    dic[name] = value;
                }
                else
                {
                    dic.Add(name, value);
                }

                return input;
            }
            else if (input is JObject jObj)
            {

                if (jObj.Properties().ToList().Count(d => d.Name == name) > 0)
                {
                    jObj.Property(name).Value = JToken.FromObject(value);
                }
                else
                {
                    jObj.Add(name, JToken.FromObject(value));
                }

                return jObj;
            }
            else
            {
                // 内置类型不支持增加属性，但可以尝试写入
                var prop = input.GetType().GetProperty(name);
                if (prop == null)
                {
                    throw new NotSupportedException("AppendProperty is NOT supported, it's neither a Dictionary<string,object> created by Huozige command or a JObject deserialized from JSON.");
                }
                else
                {
                    prop.SetValue(input, value);
                }

                return input;
            }

        }


        public static object GetObjectProperty(object input, string name, bool applyNullValue4MissingProperty = false)
        {
            if (input == null)
            {
                return null; // 如果输入为null，直接返回null
            }

            if (string.IsNullOrWhiteSpace(name) || name.ToLower() == "%value%")
            {
                return input;
            }

            if (input is IDictionary<string, object> dic)
            {
                if (dic.ContainsKey(name))
                {
                    return dic[name];
                }
                else
                {
                    if (applyNullValue4MissingProperty)
                    {
                        return null;
                    }
                    else
                    {
                        throw new ArgumentException(name + " was not found in the IDictionary<string, object> object.");
                    }

                }

            }
            else if (input is JObject jObj)
            {
                var inputObj = jObj.ToDictionary();

                if (inputObj.ContainsKey(name))
                {
                    return inputObj[name];
                }
                else
                {
                    if (applyNullValue4MissingProperty)
                    {
                        return null;
                    }
                    else
                    {
                        throw new ArgumentException(name + " was not found in the JObject object.");
                    }
                }

            }
            else
            {
                var prop = input.GetType().GetProperty(name);
                if (prop == null)
                {
                    if (applyNullValue4MissingProperty)
                    {
                        return null;
                    }
                    else
                    {
                        throw new ArgumentException(name + " was not found in the CLR object.");
                    }
                }
                else
                {
                    return prop.GetValue(input);
                }
            }

        }

        public static object GetObjectPropertyForSorting(object input, string name, bool applyNullValue4MissingProperty = false)
        {
            object rawValue = input;

            // 处理直接获取对象值的情况
            if (!string.IsNullOrWhiteSpace(name) && name.ToLower() != "%value%")
            {
                if (input is IDictionary<string, object> dic)
                {
                    if (dic.ContainsKey(name))
                    {
                        rawValue = dic[name];
                    }
                    else
                    {
                        if (applyNullValue4MissingProperty)
                        {
                            return null;
                        }
                        else
                        {
                            throw new ArgumentException(name + " was not found in the IDictionary<string, object> object.");
                        }
                    }

                }
                else if (input is JObject jObj)
                {
                    var inputObj = jObj.ToDictionary();

                    if (inputObj.ContainsKey(name))
                    {
                        rawValue = inputObj[name];
                    }
                    else
                    {
                        if (applyNullValue4MissingProperty)
                        {
                            return null;
                        }
                        else
                        {
                            throw new ArgumentException(name + " was not found in the JObject object.");
                        }
                    }

                }
                else
                {
                    var prop = input.GetType().GetProperty(name);
                    if (prop == null)
                    {
                        if (applyNullValue4MissingProperty)
                        {
                            return null;
                        }
                        else
                        {
                            throw new ArgumentException(name + " was not found in the CLR object.");
                        }
                    }
                    else
                    {
                        rawValue = prop.GetValue(input);
                    }
                }
            }

            if (rawValue is int || rawValue is double || rawValue is float || rawValue is decimal || rawValue is long || rawValue is short || rawValue is byte || rawValue is sbyte || rawValue is uint || rawValue is ulong)
            {
                // 将所有数值转化为float，虽然牺牲精度但能确保不会出现无法对比的错误。
                return Convert.ToDecimal(rawValue);
            }
            else
            {
                return rawValue;
            }

        }

        public static bool IsEqual(object xp, object yp)
        {
            if (xp is bool || xp is string || xp is int || xp is double || xp is float || xp is long || xp is short || xp is DateTime)
            {
                // 优先用字符串判等
                return xp.ToString() == yp.ToString();
            }
            else
            {
                // 其他类型，用对象判等
                return xp == yp;
            }
        }

        public static object ConvertData(object result, PropertyDataType type, object fallback)
        {
            switch (type)
            {
                case PropertyDataType.STRING:
                    return result.ToString();

                case PropertyDataType.INT:
                    if (int.TryParse(result.ToString(), out int intValue))
                    {
                        return intValue;
                    }
                    else
                    {
                        return fallback;
                    }

                case PropertyDataType.FLOAT:
                    if (float.TryParse(result.ToString(), out float doubleValue))
                    {
                        return doubleValue;
                    }
                    else
                    {
                        return fallback;
                    }
                case PropertyDataType.BOOL:

                    if (result.ToString() == "1")
                    {
                        return true;
                    }

                    if (result.ToString() == "0")
                    {
                        return false;
                    }

                    if (bool.TryParse(result.ToString(), out Boolean boolValue))
                    {
                        return boolValue;
                    }
                    else
                    {
                        return fallback;
                    }

                case PropertyDataType.DATETIME:

                    if (result is double oaDate)
                    {
                        return DateTime.FromOADate(oaDate);
                    }

                    if (DateTime.TryParse(result.ToString(), out DateTime dateTimeValue))
                    {
                        return dateTimeValue;
                    }
                    else
                    {
                        return fallback;
                    }

                case PropertyDataType.AUTO:
                default:
                    return result;
            }
        }
    }
}
